/**
 * @file user_eth1.c
 * @author Victor Lau (1345236485@qq.com)
 * @brief 
 * @version 0.1
 * @date 2023-07-19
 * 
 * @copyright Copyright (c) 2023 Victor Lau. All rights reserved.
 * 
 */
#include "user_eth1.h"
#include "include.h"

extern uint8_t ip_addr[4];
extern uint8_t sub_mask[4];
extern uint8_t gateway_buf[4];
extern uint8_t dns_buf[4];
extern int fd_eth;
extern unsigned char eth_tx_buf[1024];

/**
 * @brief submask data convert
 * 
 * @param data transfer datas
 * @return int 
 */
int submask_convert(int data)
{
        int temp_data, ret = 0, length = 0;
	int a[8];

        temp_data = data;
	while(temp_data/2)
        {
		a[length++] = temp_data%2;
		temp_data = temp_data/2;
	}
	a[length++] = temp_data%2;

	for(int i = length-1; i >= 0; i--)
        {
                ret += a[i];
        }

        return ret;
}
/***********************************
 
[Match]
Name=eth1

[Network]
Address=192.168.0.10/24
Gateway=192.168.0.1
DNS=192.168.0.1
***********************************/
void eth1_ip_modify()
{
        FILE *fp;
        char ip_address[32] = { '\0' };
        char gateway[32]       = { '\0' };
        char dns[32]                 = { '\0' };
        int submask = 0;

        // system("echo passwd | sudo -S chmod 777 /opt/*");
        if(access("/etc/network/interfaces.save", 0) == -1)
                system("sudo mv /etc/network/interfaces /etc/network/interfaces.save");
        system("sudo systemctl enable systemd-networkd");

        for(int i = 0; i < 4; i++)
        {
                submask +=  submask_convert(sub_mask[i]);
        }
        sprintf(ip_address, "Address=%d.%d.%d.%d/%d",  ip_addr[0],            ip_addr[1],           ip_addr[2],            ip_addr[3],         submask );
        sprintf(gateway,       "Gateway=%d.%d.%d.%d",       gateway_buf[0], gateway_buf[1], gateway_buf[2], gateway_buf[3]                      );
        sprintf(dns,                "DNS=%d.%d.%d.%d",                 dns_buf[0],            dns_buf[1],          dns_buf[2],           dns_buf[3]                               );

        if(access("/etc/systemd/network/eth1.network", 0) == 0)
        {
                remove("/etc/systemd/network/eth1.network");                                  // file exists and remove file
        }
        fp = fopen("/etc/systemd/network/eth1.network", "w+");
        if(fp == NULL)
        {
                printf("open file fail\n");
        }

        fwrite("\n", 1, 1, fp);
        fwrite("[Match]\n", 1, strlen("[Match]\n"), fp);
        fwrite("Name=eth1\n", 1, strlen("Name=eth1\n"), fp);
        fwrite("\n", 1, 1, fp);
        fwrite("[Network]\n", 1, strlen("[Network]\n"), fp);
        fwrite("DHCP=no\n", 1, strlen("DHCP=no\n"), fp);
        fwrite("DHCPServer=no\n", 1, strlen("DHCPServer=no\n"), fp);
        fwrite(ip_address, 1, strlen(ip_address), fp);
        fwrite("\n", 1, 1, fp);
        fwrite(gateway, 1, strlen(gateway), fp);
        fwrite("\n", 1, 1, fp);
        fwrite(dns, 1, strlen(dns), fp);
        fwrite("\n", 1, 1, fp);

        fclose(fp);
}

/**
 * @brief restore default ip address
 * 
 */
void default_ip_addr()
{
        FILE *fp;

        if(access("/etc/systemd/network/eth1.network", 0) == 0)
        {
                remove("/etc/systemd/network/eth1.network");                                  // file exists and remove file
        }
        fp = fopen("/etc/systemd/network/eth1.network", "w+");
        if(fp == NULL)
        {
                printf("open file fail\n");
        }

        fwrite("\n", 1, 1, fp);
        fwrite("[Match]\n", 1, strlen("[Match]\n"), fp);
        fwrite("Name=eth1\n", 1, strlen("Name=eth1\n"), fp);
        fwrite("\n", 1, 1, fp);
        fwrite("[Network]\n", 1, strlen("[Network]\n"), fp);
        fwrite("Address=192.168.0.10/24\n", 1, strlen("Address=192.168.0.10/24\n"), fp);
        fwrite("Gateway=192.168.0.1\n", 1, strlen("Gateway=192.168.0.1\n"), fp);
        fwrite("DNS=192.168.0.1\n", 1, strlen("DNS=192.168.0.1\n"), fp);

        fclose(fp);
}

/**
 * @brief Get the eth1 static ip object
 * 
 * @return char* 
 */
char *get_eth1_static_ip()
{
        char*   szCmd       = "cat /etc/systemd/network/eth1.network | grep Address";
        FILE*   pResultStr  = NULL;
        char  *szBuf;

        szBuf = (char *)malloc(32); 
        pResultStr = popen(szCmd, "r");
        if (NULL == pResultStr)
        {   
                printf("popen faild. (%d, %s)\n",errno, strerror(errno));
        }   

        /* 获取返回结果 */
        fread(szBuf, 1, 32, pResultStr);

        return szBuf;
}

/**
 * @brief check eth1 status
 * 
 * @return void* 
 */
void *check_eth1_status()
{
        char*   szCmd       = "cat /sys/class/net/eth1/carrier";
        FILE*   pResultStr  = NULL;
        char  szBuf[16] = {0};

        while(1)
        {
                bzero(szBuf, 16);

                /* 创建子进程，执行shell命令 */
                pResultStr = popen(szCmd, "r");
                if (NULL == pResultStr)
                {   
                        printf("popen faild. (%d, %s)\n",errno, strerror(errno));
                }   

                /* 获取返回结果 */
                fread(szBuf, 1, sizeof(szBuf), pResultStr);

                if(szBuf[0] == '1')
                        write(fd_eth, "255", 3);
                else
                        write(fd_eth, "0", 1);

                /* 不要忘记关闭句柄 */
                pclose(pResultStr);

                sleep(2);
        }
}

/**
 * @brief sub mask convert
 * 
 * @return uint32_t 
 */
uint32_t sub_mask_convert(uint8_t var)
{
	uint32_t num = 0;

	for(int i = 0; i < var; i++)
	{
		num <<= 1;
		num += 1;
	}
	
	return num;
}

/**
 * @brief binary invert
 * 
 * @param var 
 * @return uint32_t 
 */
uint32_t binary_invert(uint32_t var)
{
        int res = 0;

        for (int i = 0; i < 32; i++) 
        {
                res = (res << 1) + (var & 1);                                       // 获取 n 的最低位加到 res 上
                var >>= 1;                                                                       // n 右移一位
        }

        return res;
}

/**
 * @brief inquire eth1 static ip
 * 
 */
uint8_t inquire_eth1_static_ip()
{
        char buf[32];
        uint8_t len = 0;
        int sub_value;
        int send_buf[32];
        uint32_t sub_convert;
        FILE* pResultStr = NULL;
        char* ip_szCmd   = "cat /etc/systemd/network/eth1.network | grep Address=";
        char* gate_szCmd = "cat /etc/systemd/network/eth1.network | grep Gateway=";
        char* dns_szCmd  = "cat /etc/systemd/network/eth1.network | grep DNS=";
        char* mac_szCmd  = "ifconfig eth1 | grep ether | sed 's/^ *ether.//g' | sed 's/ .*$//g'";

        memset(send_buf, 0, 32);

        // ip
        memset(buf, 0, 32);
        pResultStr = popen(ip_szCmd, "r");
        fread(buf, 1, sizeof(buf), pResultStr);
        sscanf(buf, "Address=%d.%d.%d.%d/%d",  send_buf+0, send_buf+1, send_buf+2, send_buf+3, &sub_value);

        // sub_mask
        sub_convert = sub_mask_convert(sub_value);
        sub_convert = binary_invert(sub_convert);
        send_buf[4] = (uint8_t)(sub_convert >> 24);     
        send_buf[5] = (uint8_t)(sub_convert >> 16);
        send_buf[6] = (uint8_t)(sub_convert >> 8);
        send_buf[7] = (uint8_t)sub_convert;

        // gateway
        memset(buf, 0, 32);
        pResultStr = popen(gate_szCmd, "r");
        fread(buf, 1, sizeof(buf), pResultStr);
        sscanf(buf, "Gateway=%d.%d.%d.%d",  send_buf+8, send_buf+9, send_buf+10, send_buf+11);

        // dns
        memset(buf, 0, 32);
        pResultStr = popen(dns_szCmd, "r");
        fread(buf, 1, sizeof(buf), pResultStr);
        sscanf(buf, "DNS=%d.%d.%d.%d",  send_buf+12, send_buf+13, send_buf+14, send_buf+15);

        // mac
        memset(buf, 0, 32);
        pResultStr = popen(mac_szCmd, "r");
        fread(buf, 1, sizeof(buf), pResultStr);
        sscanf(buf, "%x:%x:%x:%x:%x:%x",  send_buf+16, send_buf+17, send_buf+18, send_buf+19, send_buf+20, send_buf+21);

        for(int i = 0; i < 22; i++)
        {
                eth_tx_buf[12 + i] = send_buf[i];
        }
        len = eth_tx_buf[5] + 22;

        pclose(pResultStr);

        return len;
}
